/**
 * 日期辅助方法 - 为小程序环境提供支持
 */

/**
 * 小程序环境安全的创建日期对象
 * 解决小程序中直接使用new Date()可能产生的问题
 * 特别处理小程序环境中日期被转为ISO字符串格式 (如 "2025-04-05T09:13:00.111Z") 的情况
 * @param {Number|String} year - 年份或ISO日期字符串
 * @param {Number} month - 月份 (0-11)
 * @param {Number} day - 日期
 * @param {Number} [hour=0] - 小时
 * @param {Number} [minute=0] - 分钟
 * @param {Number} [second=0] - 秒
 * @param {Number} [millisecond=0] - 毫秒
 * @returns {Date} 日期对象
 */
export function createDateForMP(year, month, day, hour = 0, minute = 0, second = 0, millisecond = 0) {
  try {
    // 检查第一个参数是否为ISO格式的日期字符串 (例如 "2025-04-05T09:13:00.111Z")
    if (typeof year === 'string' && year.includes('T') && (year.includes('Z') || year.includes('+'))) {
      const parsedDate = new Date(year);
      if (!isNaN(parsedDate.getTime())) {
        return parsedDate; // 直接返回解析后的日期
      }
    }
    
    // 确保输入参数是数字，并处理可能的 NaN 或无效值
    const y = isNaN(Number(year)) ? new Date().getFullYear() : Number(year);
    const m = isNaN(Number(month)) ? 0 : Number(month);
    const d = isNaN(Number(day)) ? 1 : Number(day);
    const h = isNaN(Number(hour)) ? 0 : Number(hour);
    const min = isNaN(Number(minute)) ? 0 : Number(minute);
    const s = isNaN(Number(second)) ? 0 : Number(second);
    const ms = isNaN(Number(millisecond)) ? 0 : Number(millisecond);
    
    // 创建日期对象
    const date = new Date(y, m, d, h, min, s, ms);
    
    // 检查是否为有效日期
    if (isNaN(date.getTime())) {
      console.warn('创建的日期无效，返回当前日期');
      return new Date();
    }
    
    // 特别检查月份是否被正确设置（处理JS日期溢出的问题）
    if (date.getMonth() !== m) {
      // 月份不匹配，创建月末最后一天的日期
      return new Date(y, m + 1, 0, h, min, s, ms);
    }
    
    return date;
  } catch (error) {
    console.error('创建日期时出错:', error);
    return new Date(); // 出现异常时返回当前日期
  }
}

/**
 * 获取当前系统日期，兼容小程序环境
 * @returns {Date} 当前日期对象
 */
export function getToday() {
  return new Date();
}

/**
 * 检查两个日期是否是同一天
 * @param {Date} date1 - 第一个日期
 * @param {Date} date2 - 第二个日期
 * @returns {Boolean} 是否同一天
 */
export function isSameDay(date1, date2) {
  if (!date1 || !date2) return false;
  return date1.getFullYear() === date2.getFullYear() &&
         date1.getMonth() === date2.getMonth() &&
         date1.getDate() === date2.getDate();
}

/**
 * 将日期设置为当天的开始时间 (00:00:00)
 * @param {Date} date - 日期对象
 * @returns {Date} 设置为当天开始的日期对象
 */
export function setToStartOfDay(date) {
  if (!date) return null;
  const newDate = new Date(date);
  newDate.setHours(0, 0, 0, 0);
  return newDate;
}

/**
 * 格式化日期为字符串
 * @param {Date} date - 日期对象
 * @param {String} format - 格式字符串，默认为 'YYYY-MM-DD'
 * @returns {String} 格式化后的日期字符串
 */
export function formatDate(date, format = 'YYYY-MM-DD') {
  if (!date) return '';
  
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const day = date.getDate();
  
  if (format === 'YYYY-MM-DD') {
    return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
  }
  
  return format
    .replace('YYYY', year.toString())
    .replace('MM', month.toString().padStart(2, '0'))
    .replace('DD', day.toString().padStart(2, '0'));
}

/**
 * 从格式化的日期字符串创建日期对象
 * @param {String} dateString - 格式化的日期字符串，如 "2023-01-31"
 * @param {String} format - 日期格式，默认为 'YYYY-MM-DD'
 * @returns {Date} 日期对象
 */
export function createDateFromFormatted(dateString, format = 'YYYY-MM-DD') {
  if (!dateString) return new Date();
  
  if (format === 'YYYY-MM-DD') {
    const parts = dateString.split('-');
    if (parts.length !== 3) return new Date();
    
    const year = parseInt(parts[0], 10);
    const month = parseInt(parts[1], 10) - 1; // 月份从0开始
    const day = parseInt(parts[2], 10);
    
    if (isNaN(year) || isNaN(month) || isNaN(day)) return new Date();
    
    return createDateForMP(year, month, day);
  }
  
  // 如果是其他格式，尝试直接解析
  const date = new Date(dateString);
  return isNaN(date.getTime()) ? new Date() : date;
}

/**
 * 获取当前月的天数
 * @param {Number} year - 年份
 * @param {Number} month - 月份 (0-11)
 * @returns {Number} 当月天数
 */
export function getDaysInMonth(year, month) {
  return new Date(year, month + 1, 0).getDate();
}

/**
 * 获取当月第一天是星期几
 * @param {Number} year - 年份
 * @param {Number} month - 月份 (0-11)
 * @returns {Number} 星期几 (0-6, 0表示星期日)
 */
export function getFirstDayOfMonth(year, month) {
  return new Date(year, month, 1).getDay();
}

/**
 * 获取当月最后一天是星期几
 * @param {Number} year - 年份
 * @param {Number} month - 月份 (0-11)
 * @returns {Number} 星期几 (0-6, 0表示星期日)
 */
export function getLastDayOfMonth(year, month) {
  return new Date(year, month + 1, 0).getDay();
}

/**
 * 获取日期的详细信息
 * @param {Date} date - 日期对象
 * @returns {Object|null} 日期信息对象，包含年、月、日、星期几、时间戳
 */
export function getDateInfo(date) {
  if (!date || !(date instanceof Date)) return null;
  return {
    year: date.getFullYear(),
    month: date.getMonth(),
    day: date.getDate(),
    dayOfWeek: date.getDay(),
    timestamp: date.getTime()
  };
}

/**
 * 检查日期是否在指定的年月内
 * @param {Date} date - 日期对象
 * @param {Number} year - 年份
 * @param {Number} month - 月份 (0-11)
 * @returns {Boolean} 是否在指定年月内
 */
export function isDateInYearMonth(date, year, month) {
  if (!date) return false;
  return date.getFullYear() === year && date.getMonth() === month;
}

/**
 * 获取上个月的天数
 * @param {Number} year - 当前年份
 * @param {Number} month - 当前月份 (0-11)
 * @returns {Number} 上个月的天数
 */
export function getPrevMonthDays(year, month) {
  let prevYear = year;
  let prevMonth = month - 1;
  
  if (prevMonth < 0) {
    prevYear--;
    prevMonth = 11;
  }
  
  return getDaysInMonth(prevYear, prevMonth);
}

/**
 * 解析日期字符串
 * @param {String} dateString - 日期字符串 (格式: YYYY-MM-DD)
 * @returns {Date|null} 日期对象，解析失败返回null
 */
export function parseDate(dateString) {
  if (!dateString) return null;
  
  const parts = dateString.split('-');
  if (parts.length !== 3) return null;
  
  const year = parseInt(parts[0], 10);
  const month = parseInt(parts[1], 10) - 1;
  const day = parseInt(parts[2], 10);
  
  if (isNaN(year) || isNaN(month) || isNaN(day)) return null;
  
  return createDateForMP(year, month, day);
}

/**
 * 检查值是否是有效的日期对象
 * @param {any} value - 要检查的值
 * @returns {Boolean} 是否是有效的日期对象
 */
export function isValidDate(value) {
  return value instanceof Date && !isNaN(value.getTime());
}

/**
 * 将任何日期格式转换为标准Date对象
 * @param {Date|String|Number} value - 日期值、日期字符串或时间戳
 * @returns {Date|null} 标准化的日期对象，无效则返回null
 */
export function normalizeDate(value) {
  if (!value) return null;
  
  // 如果已经是有效的Date实例
  if (value instanceof Date && !isNaN(value.getTime())) {
    return value;
  }
  
  // 如果是数字（时间戳）
  if (typeof value === 'number') {
    const date = new Date(value);
    return isNaN(date.getTime()) ? null : date;
  }
  
  // 如果是字符串，尝试解析
  if (typeof value === 'string') {
    // 尝试ISO格式
    if (value.includes('T') && (value.includes('Z') || value.includes('+'))) {
      const date = new Date(value);
      if (!isNaN(date.getTime())) {
        return date;
      }
    }
    
    // 尝试YYYY-MM-DD格式
    if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
      return parseDate(value);
    }
    
    // 尝试其他格式
    const date = new Date(value);
    if (!isNaN(date.getTime())) {
      return date;
    }
  }
  
  return null;
}

/**
 * 处理小程序环境中传递的日期参数
 * 解决从父组件传入子组件时Date被转为UTC ISO字符串的问题
 * @param {Date|String} date - 日期对象或ISO日期字符串
 * @returns {Date} 转换为本地时区的日期对象
 */
export function handleMiniProgramDate(date) {
  // 如果是null或undefined，返回null
  if (date == null) return null;
  
  // 如果已经是有效的Date对象，直接返回
  if (isValidDate(date)) return date;
  
  // 尝试使用normalizeDate处理各种格式
  const normalizedDate = normalizeDate(date);
  if (normalizedDate) return normalizedDate;
  
  // 实在无法处理时返回当前日期
  return getToday();
}

/**
 * 获取只包含年月日的时间戳（去除时分秒）
 * @param {Number|Date} dateOrTimestamp - 日期对象或时间戳
 * @returns {Number} 只包含年月日的时间戳
 */
export function getYMDTimestamp(dateOrTimestamp) {
  let date;
  if (dateOrTimestamp instanceof Date) {
    date = dateOrTimestamp;
  } else if (typeof dateOrTimestamp === 'number') {
    date = new Date(dateOrTimestamp);
  } else {
    return null;
  }
  
  return createDateForMP(
    date.getFullYear(),
    date.getMonth(),
    date.getDate()
  ).getTime();
}

/**
 * 比较两个日期的年月日是否相同（忽略时间部分）
 * @param {Date|Number} date1 - 第一个日期或时间戳
 * @param {Date|Number} date2 - 第二个日期或时间戳
 * @returns {Boolean} 是否为同一天
 */
export function isSameYMD(date1, date2) {
  const timestamp1 = getYMDTimestamp(date1);
  const timestamp2 = getYMDTimestamp(date2);
  return timestamp1 && timestamp2 && timestamp1 === timestamp2;
}

/**
 * 计算两个日期之间的天数差
 * @param {Date|Number} startDate - 开始日期或时间戳
 * @param {Date|Number} endDate - 结束日期或时间戳
 * @param {Boolean} [inclusive=true] - 是否包含开始和结束当天
 * @returns {Number} 天数差
 */
export function getDaysDiff(startDate, endDate, inclusive = true) {
  const start = getYMDTimestamp(startDate);
  const end = getYMDTimestamp(endDate);
  
  if (!start || !end) return 0;
  
  const diff = Math.abs(end - start) / (24 * 60 * 60 * 1000);
  return inclusive ? Math.round(diff) + 1 : Math.round(diff);
}

